package test;

import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;

//fattree facebook i2 st：随机选择改变类型+改变文件+改变的FIB
public class IncrementalTestChangeFile extends forwardChange{
    //fattree
/*    private static final String OUTPUT_File_PATH="config/fattree/incrementalTest/";  //改变后写入的文件夹
    private static final String PATH="config/fattree/rule/";  //改变前文件所在文件夹的路径*/

    //facebook incremental


    //i2 incremental
 /*   private static final String OUTPUT_File_PATH="config/i2Test/";  //改变后写入的文件夹
    private static final String PATH="config/i2/rule/";  //改变前文件所在文件夹的路径*/

    //st incremental    todo 设置属于st的OUTPUT_PATH  PATH 即可获得对应网络拓扑下的 FIB change
    private static final String OUTPUT_File_PATH="config/stTest/";  //改变后写入的文件夹
    private static final String PATH="config/st/";  //改变前文件所在文件夹的路径



    String change="AfterChange";   //更改后的文件的后缀


    public IncrementalTestChangeFile(){
    }


    public static void main(String[] args){
        IncrementalTestChangeFile it=new IncrementalTestChangeFile();
        it.FirstTimeFwdChange();
        for(int i=0;i<8;i++) {
            it.forwardChangeOne();
        }
    }


    //每次modify或者delete一条fwd rule，change类型和相应的文件都是随机的：core aggregation edge 确保default rule不被改变，default rule放在文件第一条
    //host没有FIB
    public ArrayList<String> forwardChangeOne(){
        ArrayList<String> type=new ArrayList<>();
        ArrayList<String> s=new ArrayList<>();
        type.add("modify");
        type.add("delete");

        int i;
        int k=getRandom(0,type.size()-1);             //变化的类型

        if(type.get(k).equals("modify")){
            i = getRandom(0,nextChangePort.size()-1);  //变化的文件
            changeFwdPortOne(nextChangePort.get(i));
            s.add(nextChangePort.get(i));
            s.add("modify");
        } else
        {
            i = getRandom(0,nextDel.size() - 1);
            delFwdOne(nextDel.get(i));
            s.add(nextDel.get(i));
            s.add("delete");
        }
        HashSet<fibLine> fc=new HashSet<>(flChange);  //变化的FIB：去重
        flChange.clear();
        flChange.addAll(fc);

        //返回需要的元素
        s.add(flChange.get(0).predicate);
        s.add(flChange.get(0).preLength);
        s.add(flChange.get(0).port);

        if(s.contains("modify")) {
            s.add(flChange.get(1).port);
        }

        return s;
    }


    //第一次读入全部
    public void FirstTimeFwdChange(){
        ArrayList<String> list = new ArrayList<>(getFileList(PATH));
        for(String s:list) {
            if (s != null) {
                readForwardFile(PATH, s);
            }
            writeIn(fl, s, change);
        }
    }

    //获取文件夹下的文件名
    public ArrayList<String> getFileList(String path) {
        ArrayList<String> list = new ArrayList<>();
        try {
            File file = new File(path);
            String[] filelist = file.list();

            for (String s:filelist) {
                list.add(s);
                nextChangePort.add(s);   //带ap
                nextDel.add(s);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    //modify：随机更改某一条的 action 从A到B
    public void changeFwdPortOne(String fileName) {
        if (fileName != null) {
            readForwardFile(OUTPUT_File_PATH, fileName, change);  //读取change
        }

        flChange.clear();
        while (true) {
            int p = getRandom(1, fl.size() - 1);  //p处的action换成和q处的action一样，保证第一条不被改变
            int q = getRandom(1, fl.size() - 1);
            if (!fl.get(p).port.equals(fl.get(q).port)) {
                fibLine b=new fibLine(fl.get(p).ruleType,fl.get(p).predicate,fl.get(p).preLength,fl.get(p).port);
                flChange.add(b); //旧
                b=new fibLine(fl.get(q).ruleType,fl.get(q).predicate,fl.get(q).preLength,fl.get(q).port);
                flChange.add(b); //新
                fl.get(p).port = fl.get(q).port;
                break;
            }
        }
        writeInTxt(fl, fileName, change);            //重新写入
    }

    //delete：每次随机删除一个
    public void delFwdOne(String fileName){
        if(fileName != null){
            readForwardFile(OUTPUT_File_PATH,fileName,change);  //读取change
        }

        flChange.clear();
        if(fl.size()==1){
            System.out.println(fileName+" 本次已经全部删除，运行结束");
            nextDel.remove(fileName);
            return; //不删除第一条
        }

        int j=1;
        if(fl.size()>2){
            j = getRandom(1,fl.size() - 1);  //不删除第一条
        }

        flChange.add(fl.get(j));
        fl.remove(j);

        writeInTxt(fl,fileName,change);   //重新写回
    }

    public void writeIn(ArrayList<fibLine> fwd,String fileName,String tail){
        try {
            File file = new File(OUTPUT_File_PATH + fileName + tail);
            if (file.exists()) {
                file.delete();
            }
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(OUTPUT_File_PATH + fileName + tail)));
            for (fibLine f : fwd) {
                if(f.ruleType.equals("fw")) {
                    pw.println(f.ruleType + " " + f.predicate + " " + f.preLength + " " + f.port);
                }
            }
            pw.close();
        }catch (Exception e) {
            System.out.println("文件写入错误!");
        }
    }



}
